﻿using Fuse8.ContentManagementFramework.Administration.Controls;
using Fuse8.ContentManagementFramework.Administration.Models;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Domain.Bases;
using Fuse8.ContentManagementFramework.Web.ApplicationRuntime;
using Fuse8.DomainFramework.BusinessService;
using Fuse8.DomainFramework.Common.Locator;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

namespace Fuse8.ContentManagementFramework.Administration.Controllers
{
    public class CmsAccountController : CmsBaseController
    {
        #region Properties

        public virtual int MaxSecondsLoginPeriod
        {
            get
            {
                return 10 * 60;
            }
        }

        public virtual int MinSecondsLoginPeriod
        {
            get
            {
                return 2;
            }
        }

        #endregion Properties

        #region Consts

        public const string LogonSalt = "cms";

        #endregion Consts

        #region Properties

        public IEnumerable<dynamic> Languages
        {
            get;
            protected set;
        }

        #endregion Properties

        #region Override methods

        protected override void Initialize(RequestContext requestContext)
        {
            Languages =
                new BusinessServiceFacade<CmsSystemLanguage, int>().FindAll()
                    .Select(p => new {Text = p.SystemLanguageName, Value = p.CultureName});

            base.Initialize(requestContext);
        }

        #endregion Override methods

        #region Common methods

        public static string GenerateTimeStamp(DateTime date)
        {
            return date.Ticks.ToString("X", CultureInfo.CurrentUICulture);
        }

        public virtual bool ValidateTimeStamp(string spin)
        {
            bool result = false;

            if (!string.IsNullOrEmpty(spin))
            {
                var time1 = DateTime.MinValue;
                var time2 = DateTime.Now;

                long tmp;
                result = long.TryParse(spin, NumberStyles.HexNumber, CultureInfo.CurrentUICulture, out tmp);
                if (result)
                {
                    time1 = new DateTime(tmp);

                    var delta = time2 - time1;

                    result = (time1 < time2) &&
                        (delta.TotalSeconds < MaxSecondsLoginPeriod) &&
                        (delta.TotalSeconds > MinSecondsLoginPeriod);
                }
            }

            return result;
        }

        #endregion Common methods

        #region View methods

        public ActionResult Logon()
        {
            return View(
                new AccountModel
                {
                    UserName = string.Empty,
                    User = string.Empty,
                    Languages = Languages,
                    TimeStamp = GenerateTimeStamp(DateTime.Now)
                });
        }

        [HttpPost]
        public ActionResult Logon(AccountModel model, string returnUrl)
        {
            ActionResult result = new EmptyResult();

            bool hasError = true;

            if (ModelState.IsValid)
            {
                if (!string.IsNullOrEmpty(returnUrl) && returnUrl.TrimEnd(new char[] { '/' }).Equals("/admin"))
                {
                    returnUrl = FormsService.DefaultUrl;
                }

                //if btn field is not empty that this was a bot
                if (string.IsNullOrEmpty(model.Btn) && string.IsNullOrEmpty(model.User))
                {
                    if (ValidateTimeStamp(model.TimeStamp))
                    {
                        if (MembershipService.ValidateUser(model.UserName, model.Password))
                        {
                            if (MembershipService.IsUserInGroup(model.UserName, PredefinedUserGroups.AdministrationAccess))
                            {
                                FormsService.SignIn(model.UserName, model.RememberMe);

                                result = !string.IsNullOrEmpty(returnUrl) ?
                                    Redirect(returnUrl) as ActionResult :
                                    RedirectToAction("Index", "CmsAdminHome") as ActionResult;

                                hasError = false;
                            }
                            else
                            {
                                ModelState.AddModelError("", GetText("The user has no sufficient rights.", "cms_Account"));
                            }
                        }
                        else
                        {
                            ModelState.AddModelError("", GetText("The user name or password provided is incorrect.", "cms_Account"));
                        }
                    }
                }
            }

            // If we got this far, something failed, redisplay form
            if (hasError)
            {
                model.Languages = Languages;
                model.TimeStamp = GenerateTimeStamp(DateTime.Now);

                result = View(model);
            }

            return result;
        }

        public ActionResult Logoff()
        {
            FormsService.SignOut();

            return RedirectToAction("Index", "CmsAdminHome");
        }

        public ActionResult ForcedPasswordChange()
        {
            return TempData[FirstLoginActionFilterAttribute.FirstLoginFilterKey] != null ?
                View() :
                RedirectToAction("Logoff", "CmsAccount") as ActionResult;
        }

        [HttpPost]
        [ValidateAntiForgeryToken(Salt = LogonSalt)]
        public ActionResult ForcedPasswordChange(ForcedPasswordChangeModel model, string returnUrl)
        {
            ActionResult result = View();

            if (ModelState.IsValid)
            {
                try
                {
                    MembershipService.UpdateUser(ContextUser, model.NewPassword, false);
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("", ex.Message);
                }

                if (ModelState.IsValid)
                {
                    result = Redirect(returnUrl);
                }
            }

            return result;
        }

        #endregion View methods

        [CmsAuthorizeAttribute]
        public ActionResult SwitchSite(int id)
        {
            var availableSites = SiteService.FindAvailableByUser(CmsContext.ContextUser);
            if (availableSites != null)
            {
                var site = availableSites.SingleOrDefault(e => e.Id == id);

                CmsContext.ContextSite = site;
            }
            return RedirectToAction("Index", "CmsAdminHome");
        }
    }
}